using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using TAAlert.BackTest;
using TALoaders;

namespace TAAlert.GUI
{
    public partial class BackTestGUI : Form
    {
        #region Private Members
        private static readonly TraceSwitch traceM = new TraceSwitch("BackTestGUI", "Debug messages in GUI EMA BackTest");

        private BackTestManager btManagerM;
        private int ixFirstValueColM;
        private BackTestDataTableBuilder dtBuilderM = new BackTestDataTableBuilder();
        #endregion

        /// <summary>Common constructor initializing the GUI components</summary>
        /// <param name="ticker">Security ticker</param>
        /// <param name="startDate">Back-test start date</param>
        /// <param name="endDate">Back-test end date</param>
        /// <param name="sigType">Quote type generating the signals</param>
        private BackTestGUI(string ticker, string loaderName, DateTime startDate, DateTime endDate, double trancsactionCost, QuoteType sigType, bool showYearlyPerf, bool showMonthlyPerf)
        {
            Debug.WriteLineIf(traceM.TraceInfo, "--> BackTestGUI: Constructing for " + ticker + ", loader=" + loaderName + ", from: " + startDate.ToShortDateString() + ", to: " + endDate.ToShortDateString() +
                ", tc=" + trancsactionCost + ", sigType=" + sigType.ToString() + ", showYearly=" + showYearlyPerf + ", showMonthly=" + showMonthlyPerf);
            Debug.Indent();

            Loader loader = (Loader) Enum.Parse(typeof(Loader), loaderName);
            this.btManagerM = new BackTestManager(ticker, loader, startDate, endDate, trancsactionCost, sigType, showYearlyPerf, showMonthlyPerf);
            InitializeComponent();
        }

        /// <summary>Common constructor finilizing the GUI components</summary>
        /// <param name="dTable">Data to be shown. Start with parameter columns followed by value columns</param>
        private void commonConstructorFinalizer(DataTable dTable)
        {
            this.dgViewM.DataSource = dTable;
            // Format columns
            for (int ix = 0; ix < dTable.Columns.Count; ++ix)
            {
                DataGridViewColumn col = this.dgViewM.Columns[ix];
                col.DefaultCellStyle.Format = (string)dTable.Columns[ix].ExtendedProperties[BackTestDataTableBuilder.FORMAT_EXT_PROPERTY];
                if (ix < this.ixFirstValueColM)
                    col.DefaultCellStyle.BackColor = Color.AliceBlue;
            }
            dgViewM.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
            Debug.Unindent();
        }

        /// <summary>Constructor used for (single) EMA back-test</summary>
        /// <param name="ticker">Security ticker</param>
        /// <param name="loaderName">Loader  used to get data</param>
        /// <param name="startDate">Back-testing start date</param>
        /// <param name="endDate">Back-testing end date</param>
        /// <param name="nMIN">min value of EMA period (inclusive)</param>
        /// <param name="nMAX">max value of EMA period (inclusive)</param>
        /// <param name="showYearlyPerf">Is yearly performance to be shown?</param>
        /// <param name="showMonthlyPerf">Is monthly performance to be shown?</param>
        public BackTestGUI(string ticker, string loaderName, DateTime startDate, DateTime endDate,
                           int nMIN, int nMAX, int step, bool showYearlyPerf, bool showMonthlyPerf,
                           double transactionCost, QuoteType sigType)
            : this(ticker, loaderName, startDate, endDate, transactionCost, sigType, showYearlyPerf, showMonthlyPerf)
        {
            Debug.WriteLineIf(traceM.TraceInfo, "nMIN=" + nMIN + ", nMAX=" + nMAX + ", step=" + step);
            ixFirstValueColM = 1;
            SortedList<int, BackTestManager.PerfSummary> emaPerfList = this.btManagerM.backTestEMAStrategy(nMIN, nMAX, step);
            DataTable table = dtBuilderM.createEMABackTest(emaPerfList, showYearlyPerf, showMonthlyPerf);
            
            this.Text = this.createFormTitle(StrategyName.EMA, ticker, transactionCost, sigType);
            this.commonConstructorFinalizer(table);
        }

        /// <summary>Constructor used for MACD back test</summary>
        public BackTestGUI(string ticker, string loaderName, DateTime startDate, DateTime endDate,
                        int nShortMIN, int nShortMAX, int shortStep,
                        int nLongMIN, int nLongMAX, int longStep,
                        int nFastMIN, int nFastMAX, int fastStep,
                        bool showYearlyPerf, bool showMonthlyPerf, double transactionCost, QuoteType sigType)
            : this(ticker, loaderName, startDate, endDate, transactionCost, sigType, showYearlyPerf, showMonthlyPerf)
        {
            ixFirstValueColM = 3;
            List<BackTestManager.MACDPerfSummary> macdPerfList = this.btManagerM.backTestMACDStrategy(nShortMIN, nShortMAX, shortStep, nLongMIN, nLongMAX, longStep, nFastMIN, nFastMAX, fastStep);
            DataTable table = this.dtBuilderM.createMACDDataTable(macdPerfList, showYearlyPerf, showMonthlyPerf);
            this.Text = this.createFormTitle(StrategyName.EMA, ticker, transactionCost, sigType);
            this.commonConstructorFinalizer(table);
        }

        /// <summary>Constructor used for VEMA and TwoEMA back-tests</summary>
        public BackTestGUI(StrategyName strategy, string ticker, string loaderName, DateTime startDate, DateTime endDate,
            int n1MIN, int n1MAX, int step1, int n2MIN, int n2MAX, int step2,
            double volMIN, double volMAX, double volSTEP,
            bool showYearlyPerf, bool showMonthlyPerf, double transactionCost, QuoteType sigType)
            : this(ticker, loaderName, startDate, endDate, transactionCost, sigType, showYearlyPerf, showMonthlyPerf)
        {
            ixFirstValueColM = 3;
            DataTable table;
            switch (strategy)
            {
                case StrategyName.VEMA:
                    List<BackTestManager.VEMAPerfSummary> vemaPerfList = this.btManagerM.backTestVEMAStrategy(n1MIN, n1MAX, step1, n2MIN, n2MAX, step2, volMIN, volMAX, volSTEP);
                    table = this.dtBuilderM.createVEMATable(vemaPerfList, showYearlyPerf, showMonthlyPerf);
                    this.Text = this.createFormTitle(StrategyName.EMA, ticker, transactionCost, sigType);
                    break;
                case StrategyName.TwoEMA:
                    List<BackTestManager.TwoEmaPerfSummary> twoEmaPerfList = this.btManagerM.backTestTwoEMAStrategy(n1MIN, n1MAX, step1, n2MIN, n2MAX, step2, volMIN, volMAX, volSTEP);
                    table = this.dtBuilderM.createTwoEMADataTable(twoEmaPerfList, showYearlyPerf, showMonthlyPerf);
                    this.Text = this.createFormTitle(StrategyName.EMA, ticker, transactionCost, sigType);
                    break;
                default:
                    throw new Exception("BackTestGUI constructor called with wrong strategy: " + strategy.ToString());
            }
            this.commonConstructorFinalizer(table);
        }

        /// <summary>String used for Form Title</summary>
        private string createFormTitle(StrategyName strategy, string ticker, double transCost, QuoteType sigType)
        {
            return strategy.ToString() + ": " + ticker + 
                ", from:" + this.dtBuilderM.FirstDate.ToShortDateString() + ", to:" + this.dtBuilderM.LastDate.ToShortDateString()+
                ". TC=" + transCost.ToString("#.##%") + ", Quote=" + sigType.ToString();
        }

        /// <summary>Color formatting of Calmar ratio results. Green for profitable and red for loosing strategies</summary>
        private void dgViewM_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            // Ensure that the value is a string.
            if (e != null && e.Value != null)
            {
                if (e.ColumnIndex >= this.ixFirstValueColM)
                {
                    double dValue;
                    if (Double.TryParse(e.Value.ToString(), out dValue))
                    {
                        if (dValue < -0.6)
                            e.CellStyle.BackColor = Color.Red;
                        else if (dValue < 0)
                            e.CellStyle.BackColor = Color.LightPink;
                        else if (dValue > 5)
                            e.CellStyle.BackColor = Color.Green;
                        else if (dValue > 2)
                            e.CellStyle.BackColor = Color.SpringGreen;
                        else if (dValue > 1)
                            e.CellStyle.BackColor = Color.PaleGreen;
                    }
                }
            }

        }

        /// <summary>Save table to excel</summary>
        private void saveToExcel(object sender, EventArgs e)
        {
            Debug.WriteLine(traceM.TraceInfo, "saveToExcel called...");

            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".csv";
            dlg.Filter = "Alert files (*.csv)|*.csv";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                DataTable dTable = (DataTable)this.dgViewM.DataSource;
                string fileName = dlg.FileName;
                Utilities.saveDataTableToCSV(fileName, dTable);
                Debug.WriteLineIf(traceM.TraceInfo, " saved to " + fileName);
            }
            else
                Debug.WriteLineIf(traceM.TraceInfo, " NOT SAVED!!");

        }
    }
}